﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EnvDTE80;
using SPVisualDev.VSAddin.UserControls;
using EnvDTE;

namespace SPVisualDev.VSAddin.Dialogs
{
    public partial class DialogTargets : Form
    {
        private SpecialProject m_project;
        private bool m_has_changes;
        private List<string[]> m_targets;
        private Dictionary<string, string> m_features;
        private string m_feature_name;
        private RadioButton m_last_selected_scope;

        public DialogTargets(SpecialProject specialProject, string FeatureName)
        {
            InitializeComponent();

            m_project = specialProject;
            m_feature_name = FeatureName;

            this.Load += new EventHandler(DialogTargets_Load);
            this.FormClosing += new FormClosingEventHandler(DialogTargets_FormClosing);
            this.lstTargets.ItemChecked += new ItemCheckedEventHandler(lstTargets_ItemChecked);
            this.lstTargets.AfterLabelEdit += new LabelEditEventHandler(lstTargets_AfterLabelEdit);

            this.rdoApplyTargetsForFeature.CheckedChanged += new EventHandler(rdoApplyTargetsForSolution_CheckedChanged);
            this.rdoApplyTargetsForProject.CheckedChanged += new EventHandler(rdoApplyTargetsForSolution_CheckedChanged);
            this.rdoApplyTargetsForSolution.CheckedChanged += new EventHandler(rdoApplyTargetsForSolution_CheckedChanged);
        }

        void rdoApplyTargetsForSolution_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                RadioButton selected;
                if (this.rdoApplyTargetsForFeature.Checked)
                {
                    selected = this.rdoApplyTargetsForFeature;
                    this.lblTargetsHeading.Text = "Targets for this feature";
                    this.Text = "Targets for feature " + m_feature_name;
                }
                else if (this.rdoApplyTargetsForProject.Checked)
                {
                    selected = this.rdoApplyTargetsForProject;
                    this.lblTargetsHeading.Text = "Targets for this project";
                    this.Text = this.lblTargetsHeading.Text;
                }
                else
                {
                    selected = this.rdoApplyTargetsForSolution;
                    this.lblTargetsHeading.Text = "Targets for this solution";
                    this.Text = this.lblTargetsHeading.Text;
                }

                if (m_last_selected_scope == selected)
                    return;

                if (m_has_changes)
                {
                    if (MessageBox.Show("Discard changes?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.Yes)
                    {
                        m_last_selected_scope.Checked = true;
                        return;
                    }
                }

                if (this.rdoApplyTargetsForFeature.Checked)
                    m_last_selected_scope = this.rdoApplyTargetsForFeature;
                else if (this.rdoApplyTargetsForProject.Checked)
                    m_last_selected_scope = this.rdoApplyTargetsForProject;
                else
                    m_last_selected_scope = this.rdoApplyTargetsForSolution;

                try
                {
                    RefreshTargetsList();
                }
                catch (Exception ex)
                {
                    throw new Exception("Failed to render targets list. " + ex.ToString());
                }

                m_has_changes = false;

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        void lstTargets_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            m_has_changes = true;
        }

        void lstTargets_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            m_has_changes = true;
        }

        void DialogTargets_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.DialogResult == DialogResult.OK)
                return;

            if ((e.CloseReason == CloseReason.UserClosing || e.CloseReason == CloseReason.None) && m_has_changes)
            {
                if (MessageBox.Show("Discard changes?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.No)
                {
                    e.Cancel = true;
                }
            }
        }

        public bool Force
        {
            get { return this.chkForce.Checked; }
            set { this.chkForce.Checked = value; }
        }

        internal UCSPExplorer SPExplorer
        {
            get { return this.ucspExplorer1; }
        }

        public bool HasChanges
        {
            get { return m_has_changes; }
        }

        public string OKButtonText
        {
            get { return this.btnOK.Text; }
            set { this.btnOK.Text = value; }
        }

        public List<string[]> Targets
        {
            get
            {
                List<string[]> targets = new List<string[]>();
                foreach (ListViewItem item in this.lstTargets.Items)
                {
                    targets.Add(new string[] { item.Text, item.SubItems[1].Text, item.Checked.ToString() });
                }
                return targets;
            }
        }

        public string InfoMessage
        {
            get { return this.lblInfo.Text; }
            set { this.lblInfo.Text = value; }
        }

        void DialogTargets_Load(object sender, EventArgs e)
        {
            this.SPExplorer.ViewType = 1;

            this.SPExplorer.ShowContentTypeGroups = false;
            this.SPExplorer.ShowContentTypes = false;
            this.SPExplorer.ShowFields = false;
            this.SPExplorer.ShowSolutions = false;
            this.SPExplorer.ShowFeatures = false;
            this.SPExplorer.ShowLists = false;

            this.SPExplorer.InitExplorer(m_project.Project.DTE as DTE2, m_project, 0);

            LoadConfig();


            if (m_feature_name == null)
            {
                this.rdoApplyTargetsForFeature.Enabled = false;
                this.btnOK.Text = "Save";
            }

            m_has_changes = false;
        }

        private void LoadConfig()
        {
            this.lstTargets.Items.Clear();

            m_targets = new List<string[]>();
            m_features = new Dictionary<string, string>();

            string scope = "Feature";

            ProjectItem featuresFolder = null;
            List<string> listOfProjectFeatures = new List<string>();
            try
            {
                featuresFolder = m_project.Project.ProjectItems.Item("12").ProjectItems.Item("Template").ProjectItems.Item("Features");

                foreach (ProjectItem item in featuresFolder.ProjectItems)
                {
                    if (item.Kind != Constants.vsProjectItemKindPhysicalFolder)
                        continue;

                    listOfProjectFeatures.Add(item.Name.ToLower());
                }
            }
            catch { }

            string targetUrlsString = m_project.GetUserSettingsValue("FeatureActivationTargetSettings");
            if (targetUrlsString != null)
            {
                bool bFound = false;
                if (targetUrlsString.IndexOf("$") != -1)
                {
                    string[] segments = targetUrlsString.Split('$');

                    foreach (string segment in segments)
                    {
                        string[] arr = segment.Split(';');
                        if (string.IsNullOrEmpty(arr[0]))
                            continue;

                        if (arr[0] == m_feature_name)
                        {
                            bFound = true;
                            scope = arr[1];
                        }

                        string s = "";
                        for (int i = 1; i < arr.Length; i++)
                        {
                            if (s != "")
                                s += ";";

                            s += arr[i];
                        }

                        if (listOfProjectFeatures.Contains(arr[0].ToLower()))
                        {
                            m_features.Add(arr[0], s);
                        }
                    }
                }

                if (!bFound)
                {
                    targetUrlsString = m_project.GetUserSettingsValue("FeatureActivationTargetUrls");
                    if (!string.IsNullOrEmpty(targetUrlsString))
                    {
                        scope = "Project";
                    }
                    else
                    {
                        targetUrlsString = m_project.GetUserSettingsValue("FeatureActivationSolutionTargetUrls");
                        if (!string.IsNullOrEmpty(targetUrlsString))
                        {
                            scope = "Solution";
                        }
                    }
                }
            }
            else
            {
                //For backward compatibility
                scope = "Project";
            }

            if (scope == "Solution")
            {
                this.rdoApplyTargetsForSolution.Checked = true;
            }
            else if (scope == "Project")
            {
                this.rdoApplyTargetsForProject.Checked = true;
            }
            else
            {
                if (m_feature_name != null)
                    this.rdoApplyTargetsForFeature.Checked = true;
                else
                    this.rdoApplyTargetsForProject.Checked = true;
            }

        }

        private void RefreshTargetsList()
        {
            string[] targetUrls = new string[0];

            this.lstTargets.Items.Clear();

            if (this.rdoApplyTargetsForFeature.Checked)
            {
                if (m_features.ContainsKey(m_feature_name))
                {
                    string s = m_features[m_feature_name];
                    targetUrls = s.Split(';').Skip<string>(1).ToArray<string>();
                }
            }
            else if (this.rdoApplyTargetsForProject.Checked)
            {
                string s = m_project.GetUserSettingsValue("FeatureActivationTargetUrls");
                if (string.IsNullOrEmpty(s))
                    return;

                targetUrls = s.Split(';');
            }
            else
            {
                string s = m_project.SpecialSolution.GetUserSettingsValue("FeatureActivationSolutionTargetUrls");
                if (string.IsNullOrEmpty(s))
                    return;

                targetUrls = s.Split(';');
            }


            foreach (string nameUrlPair in targetUrls)
            {
                string[] arr = nameUrlPair.Split('|');
                string name;
                string url;

                if (arr.Length == 1)
                {
                    //For backwards compativbility version < 2

                    name = arr[0].Replace("_0x007C_", "|").Replace("_0x003B_", ";").Replace("_0x0024_", "$");
                    url = name;

                    ListViewItem item = new ListViewItem(new string[] { name, url });
                    item.Checked = true;

                    this.lstTargets.Items.Add(item);

                }
                else
                {
                    name = arr[0].Replace("_0x007C_", "|").Replace("_0x003B_", ";").Replace("_0x0024_", "$");
                    url = arr[1].Replace("_0x007C_", "|").Replace("_0x003B_", ";").Replace("_0x0024_", "$");

                    ListViewItem item = new ListViewItem(new string[] { name, url });
                    item.Checked = (arr[2] == "True");

                    this.lstTargets.Items.Add(item);
                }
            }
        }

        private void btnAddToTargets_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(this.SPExplorer.SelectedUrl))
                    return;

                bool b = this.Targets.Exists(s => s[1].Equals(this.SPExplorer.SelectedUrl, StringComparison.OrdinalIgnoreCase));
                if (!b)
                {
                    ListViewItem item = new ListViewItem(new string[] { this.SPExplorer.SelectedTitle, this.SPExplorer.SelectedUrl });
                    item.Checked = true;

                    this.lstTargets.Items.Add(item);

                    m_has_changes = true;
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        private void Remove_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.lstTargets.SelectedItems.Count == 0)
                    return;

                foreach (ListViewItem item in this.lstTargets.SelectedItems)
                {
                    this.lstTargets.Items.Remove(item);
                }

                m_has_changes = true;

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        private void btnAddURL_Click(object sender, EventArgs e)
        {
            try
            {
                using (DialogInputBox inputDialog = new DialogInputBox())
                {
                    inputDialog.Text = "Add target URL";
                    inputDialog.InfoMessage = "Enter an URL to add to the list of targets.";
                    inputDialog.InputText = "http://";

                    DialogResult result = inputDialog.ShowDialog(this);
                    if (result != DialogResult.OK || string.IsNullOrEmpty(inputDialog.InputText))
                        return;

                    if (!inputDialog.InputText.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
                        return;

                    ListViewItem item = new ListViewItem(new string[] { GetNameFromURL(inputDialog.InputText), inputDialog.InputText });
                    item.Checked = true;

                    this.lstTargets.Items.Add(item);

                    m_has_changes = true;
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        private string GetNameFromURL(string URL)
        {
            string ret;
            int i = URL.LastIndexOf('/');
            if (i != 1)
            {
                ret = (i + 1 <= URL.Length) ? URL.Substring(i + 1) : URL.Substring(i);
            }
            else
            {
                ret = URL;
            }

            return ret;
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            try
            {
                SaveSettings();

                this.DialogResult = DialogResult.OK;
                this.Hide();
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        private void SaveSettings()
        {
            string scope;

            if (this.rdoApplyTargetsForSolution.Checked)
            {
                scope = "Solution";
            }
            else if (this.rdoApplyTargetsForProject.Checked)
            {
                scope = "Project";
            }
            else
            {
                scope = "Feature";
            }

            string targets1 = "";
            string targets2 = "";

            if (m_feature_name != null)
            {
                targets1 = "$" + m_feature_name + ";" + scope;
            }
                
            foreach (string[] arr in this.Targets)
            {
                if (targets1 != "")
                    targets1 += ";";

                if (targets2 != "")
                    targets2 += ";";

                arr[0] = arr[0].Replace("|", "_0x007C_").Replace(";", "_0x003B_").Replace("$", "_0x0024_");
                arr[1] = arr[1].Replace("|", "_0x007C_").Replace(";", "_0x003B_").Replace("$", "_0x0024_");

                targets1 += arr[0] + "|" + arr[1] + "|" + arr[2];
                targets2 += arr[0] + "|" + arr[1] + "|" + arr[2];
            }

            if (m_feature_name != null)
            {
                if (!m_features.ContainsKey(m_feature_name))
                {
                    m_features.Add(m_feature_name, targets1);
                }
                else
                {
                    m_features[m_feature_name] = targets1;
                }
            }


            if (scope == "Solution")
            {
                m_project.SpecialSolution.SetUserSettingsValue("FeatureActivationSolutionTargetUrls", targets2, true);
            }
            else if (scope == "Project")
            {
                m_project.SetUserSettingsValue("FeatureActivationTargetUrls", targets2, true);
            }

            targets1 = "";
            foreach (KeyValuePair<string, string> kvp in m_features)
            {
                targets1 += "$" + kvp.Key.Replace("$", "_");

                if (kvp.Key == m_feature_name)
                {
                    targets1 += ";" + scope;

                    if (scope == "Feature")
                    {
                        foreach (string[] arr in this.Targets)
                        {
                            if (targets1 != "")
                                targets1 += ";";

                            arr[0] = arr[0].Replace("|", "_0x007C_").Replace(";", "_0x003B_").Replace("$", "_0x0024_");
                            arr[1] = arr[1].Replace("|", "_0x007C_").Replace(";", "_0x003B_").Replace("$", "_0x0024_");

                            targets1 += arr[0] + "|" + arr[1] + "|" + arr[2];
                        }
                    }
                }
                else
                {
                    targets1 += ";" + kvp.Value;
                }
            }


            m_project.SetUserSettingsValue("ForceFeatureAction", this.Force.ToString(), false);
            m_project.SetUserSettingsValue("FeatureActivationTargetSettings", targets1, true);
        }
    }
}
